<script type="text/x-template" id="my-select">
    <el-select style="width: 100%" v-bind="$props" @change="$emit('change',$event)" v-model="select"
               filterable :filter-method="dataFilter" :reserve-keyword="true" :placeholder="placeholder"
               clearable @visible-change="visibleChange" :default-first-option="true"
               :title="searchData.type||res">
        <slot name="options"></slot>
        <div v-infinite-scroll="loadMore" :infinite-scroll-disabled="loadMoreFlag" :infinite-scroll-distance="50">
            <el-option v-for='(item,i) in options' :key="prop.value(item)" :value="prop.value(item)"
                       :label="prop.label(item)">({{i + 1}}) {{prop.label(item)}}
            </el-option>
        </div>
    </el-select>
</script>
<script>
    (function () {
        const cache = {};
        const dictStr = "_@@_";

        const mySelectConfig = {
            dict: {
                url: my.base + '/common/select/dict',
                searchField: 'name',
                prop: {
                    value: (item) => {
                        return item['type'] + dictStr + item['id'];
                    },
                    label: (item) => {
                        return item['name'];
                    }
                },
                getSelect(that) {
                    let v = that.value;
                    //配合 multiple 使用
                    if (that.multiple) {
                        let selectArr = [];
                        if (v instanceof Array) {
                            selectArr = that.value;
                        } else if (v) {
                            selectArr = that.value.split(",")
                        }
                        for (let i = 0; i < selectArr.length; i++) {
                            let tv = selectArr[i];
                            if (tv && tv.indexOf(dictStr) === -1) {
                                tv = that.searchData.type + dictStr + tv;
                            }
                        }

                        return selectArr;
                    } else if (v && v.indexOf(dictStr) === -1) {
                        return that.searchData.type + dictStr + v;
                    }
                    return v;
                }
            },
            user: {
                url: my.base + '/common/select/user',
                prop: {
                    value: (item) => {
                        return item['id'];
                    },
                    label: (item) => {
                        if(item['officeName']){
                            return "【" + item['officeName'] + '】' + item['name'];
                        }
                        return item['name'];
                    }
                },
            },
            project: {
                url: my.base + '/common/select/project'
            },
            projectQMIS: {
                url: my.base + '/common/select/projectQMIS'
            },
            modelConfig: {
                url: my.base + '/common/select/modelConfig'
            },
            line: {
                url: my.base + '/res/productline/queryPage'
            },
            projectCodeName: {
                url: my.base + '/common/select/projectCodeName'
            },
            materialCode: {
                url: my.base + '/common/select/materialCode'
            },
            materialName: {
                url: my.base + '/common/select/materialName'
            },
            materialNameAndCode: {
                url: my.base + '/common/select/materialNameAndCode'
            },

            trialWorkStation: {
                url: my.base + '/common/select/trialWorkStation'
            },

            supplier: {
                url: my.base + '/res/supplier/queryPage',
                searchField: 'name',
                prop: {
                    value: (item) => {
                        return item['id'];
                    },
                    label: (item) => {
                        return item['name'];
                    }
                }
            },
            supplierList: {
                url: my.base + '/res/supplier/supplierQueryPage',
                searchField: 'name',
                prop: {
                    value: (item) => {
                        return item['id'];
                    },
                    label: (item) => {
                        return item['name'];
                    }
                }
            },
            parts: {
                url: my.base + '/res/simulatedelivery/select',
                searchField: 'name',
                prop: {
                    value: (item) => {
                        return item['id'];
                    },
                    label: (item) => {
                        return item['name'] + "(" + item['code'] + ")";
                    }
                }
            },
            // 工具
            tool: {
                url: my.base + '/res/toolbase/queryPage',
                searchField: 'name',
                prop: {
                    value: (item) => {
                        return item['id'];
                    },
                    label: (item) => {
                        return item['name'];
                    }
                }
            },
            // 计量工具
            measuringTool: {
                url: my.base + '/res/toolbase/queryMeasuringPage',
                searchField: 'name',
                prop: {
                    value: (item) => {
                        return item['id'];
                    },
                    label: (item) => {
                        return item['name'] + ' ' + item['model'];
                    }
                }
            },
            inspectCraftProcess: {
                url: my.base + '/qmis/inspect/schemeCraft/queryPage',
                searchField: 'processName',
                prop: {
                    value: (item) => {
                        return item['processId'];
                    },
                    label: (item) => {
                        return item['processName'];
                    }
                }
            },
            inspectCraftProcessCode: {
                url: my.base + '/qmis/inspect/schemeCraft/queryPage',
                searchField: 'processName',
                prop: {
                    value: (item) => {
                        return item['processCode'];
                    },
                    label: (item) => {
                        return item['processName'];
                    }
                }
            },
            inspectActionGroup: {
                url: my.base + '/dtp/process/actiongroup/queryPage'
            },
            inspectAction: {
                url: my.base + '/dtp/process/actiongroup/queryPage'
            },
            actionGroup: {
                url: my.base + '/dtp/process/actiongroup/queryPage'
            },
            actionId: {
                url: my.base + '/dtp/process/actiongroup/queryActionPage',
                searchField: 'actionName',
                prop: {
                    value: (item) => {
                        return item['id'];
                    },
                    label: (item) => {
                        return item['actionName'];
                    }
                }
            }
        }

        const props = Object.assign({
            placeholder: {
                type: String,
                default() {
                    return "请选择";
                }
            },
            cache: {
                type: Boolean,
                default() {
                    return true;
                }
            },
            expTime: {
                type: Number,
                default() {
                    return 100000;
                }
            },
            index: Number,
            pageSize: {
                type: Number,
                default() {
                    return 1000;
                }
            },
            dictType: {
                type: String,
                default() {
                    return null;
                }
            },
            url: String,
            res: String,
            // vtmk => variableTypeMap 的 KEY
            vtmk: String,
            actVar: String,
            nodeVar: String,
            masterVar: String,
            dataList: {
                type: Array,
                default() {
                    return [];
                }
            },
            dataMap: {
                type: Object,
                default() {
                    return {};
                }
            },
            searchField: {
                type: String,
                default() {
                    return 'name';
                }
            },
            searchData: {
                type: Object,
                default() {
                    return {};
                }
            },
            prop: {
                type: Object,
                default() {
                    return {
                        isDefault: true,
                        value: (item) => {
                            return item['id'];
                        },
                        label: (item) => {
                            return item['name'];
                        }
                    };
                }
            },
            resConfig: {
                type: Object,
                default() {
                    return {};
                }
            },
            handleResp: {
                type: Function
            },
            getSelect: {
                type: Function
            },
            defaultSelect: {
                type: Object,
                default() {
                    return null;
                }
            }
        }, Vue.options.components.ElSelect.options.props);

        Vue.component('my-select', {
            template: '#my-select',
            props: props,
            data() {
                return {
                    myLoading: false,
                    initFlag: false,
                    loadMoreFlag: false,
                    page: {
                        records: null,
                        pageTotal: null,
                        pageNo: 1,
                        pageSize: null
                    },
                    select: [],
                    optionsCopy: [],
                    options: [],
                    queueVal: [],
                    myGetSelect: function (that) {
                        let v = that.value;
                        //配合 multiple 使用
                        if (that.multiple) {
                            if (v instanceof Array) {
                                return that.value;
                            } else if (v) {
                                return that.value.split(",");
                            } else {
                                return [];
                            }
                        } else {
                            return v;
                        }
                    },
                    myHandleResp: function (t, res) {
                        if (t.page.pageSize > 0) {
                            t.page.pageNo = res.pageNo;
                            t.page.pageTotal = res.total;
                            t.page.records = res.records;
                            if (t.page.records) {
                                if (t.page.pageNo === 1) {
                                    t.options = res.list || res.rows;
                                } else {
                                    t.options.push.apply(t.options, res.list || res.rows);
                                }
                                t.loadMoreFlag = t.options.length >= t.page.records;
                            } else {
                                t.options = res.list || res.rows;
                                t.loadMoreFlag = true;
                            }

                        } else {
                            t.options = res.list || res.rows;
                        }
                        t.optionsCopy = myUtil.copyObj(t.options);
                    }
                }
            },
            watch: {
                select: {
                    handler: function (n, o) {
                        if (n === undefined) {
                            return;
                        }

                        this.myEmit(n);
                    }
                },
                value: function (n, o) {
                    this.setSelect();
                },
                res: function (n, o) {
                    this.page.pageNo = 1;
                    this.load();
                    this.$emit('init', this.$parent.prop, this);
                },
                searchData: {
                    handler(n, o) {
                        if (n) {
                            this.page.pageNo = 1;
                            this.load();
                        }
                    },
                    deep: true
                },
                dataList: {
                    handler(n, o) {
                        this.init();
                    },
                    deep: true
                },
                dataMap: {
                    handler(n, o) {
                        if (!n && !o) {
                            return;
                        }

                        let nl = [];
                        if (n) {
                            for (let key in n) {
                                if (n.hasOwnProperty(key)) {
                                    nl.push({name: n[key], id: key})
                                }
                            }
                        }

                        this.dataList = myUtil.copyObj(nl);
                    },
                    deep: true,
                    immediate: true
                }
            },
            methods: {
                init() {
                    let that = this;
                    myUtil.mergeVueData(that, that.optionsCopy, that.dataList);
                    if (that.dictType) {
                        that.searchData.type = that.dictType;
                        that.res = "dict";
                    }
                    that.page.pageSize = that.pageSize;
                    that.page.pageNo = 1;
                    that.initFlag = true;
                    that.load();
                    that.$emit('init', that.$parent.prop, that);
                },
                load() {
                    if (!this.initFlag) {
                        return;
                    }
                    this.setRes(this.res);
                    this.list();
                    this.setSelect();
                },
                loadMore() {
                    this.page.pageNo = 1 + this.page.pageNo;
                    this.load();
                },
                visibleChange(show) {
                    if (show) {
                        this.loadMoreFlag = false;
                        this.dataFilter();
                    }
                },
                dataFilter(val) {
                    if (this.page.pageSize > 0 && !this.loadMoreFlag && (this.url || this.res)) {
                        if (!val) {
                            delete this.searchData[this.searchField];
                        } else {
                            this.searchData[this.searchField] = val;
                        }
                        this.page.pageNo = 1;
                        this.load();
                    } else {
                        if (val) {
                            let that = this;
                            this.options = this.optionsCopy.filter((item) => {
                                if (!!~that.prop.label(item).indexOf(val) || !!~that.prop.label(item).toUpperCase().indexOf(val.toUpperCase())) {
                                    return true
                                }
                            })
                        } else {
                            this.options = myUtil.copyObj(this.optionsCopy);
                        }
                    }
                },
                setRes(res) {
                    if (!res) {
                        return;
                    }

                    this.resConfig = mySelectConfig[res]
                    if (this.resConfig) {
                        this.url = this.resConfig.url || this.url;
                        this.prop = this.resConfig.prop || this.prop;
                        this.myHandleResp = this.resConfig.handleResp || this.handleResp || this.myHandleResp;
                        this.myGetSelect = this.resConfig.getSelect || this.getSelect || this.myGetSelect;
                    } else {
                        this.url = this.url || my.base + '/common/select/' + res;
                    }
                },
                list() {
                    let that = this;
                    let url = that.url;
                    if (!url && !that.res) {
                        myUtil.mergeVueData(that, that.options, that.dataList);
                        that.defaultSelectFunc();
                        return;
                    }
                    let searchData = that.searchData;
                    if (searchData && searchData.unQuery) {
                        return;
                    }
                    if (that.myLoading) {
                        return;
                    }
                    that.myLoading = true;

                    let httpSearchData = myUtil.copyObj(searchData);
                    if (that.page && that.page.pageSize > 0) {
                        httpSearchData = Object.assign(httpSearchData, that.page);
                    }

                    let cacheKey = url + JSON.stringify(httpSearchData);
                    let cacheData = that.getCache(cacheKey);

                    let promise;

                    if (cacheData) {
                        promise = new Promise((resolve, reject) => {
                            if (cacheData.myLoading) {
                                let interval = setInterval(() => {
                                    cacheData = that.getCache(cacheKey);
                                    if (!cacheData || !cacheData.myLoading) {
                                        clearInterval(interval);
                                        resolve(cacheData);
                                    }
                                }, 200);
                            } else {
                                resolve(cacheData);
                            }
                        })
                    } else {
                        that.setCache(cacheKey, {myLoading: true});
                        promise = my.http.postJson(url, httpSearchData);
                    }

                    promise.then(function (res) {
                        that.setCache(cacheKey, res);
                        that.myHandleResp(that, res);
                        that.defaultSelectFunc();
                        that.myLoading = false;
                    }).catch(function (err) {
                        that.myLoading = false;
                        console.log(err);
                    })
                },
                defaultSelectFunc(){
                    let that = this;
                    if (that.value === null || that.value === undefined) {
                        let defaultSelect = that.defaultSelect;
                        if (that.options && that.options.length > 0 && defaultSelect !== null && defaultSelect !== undefined) {
                            // 设置默认值
                            if (that.multiple) {
                                if (typeof defaultSelect === 'string') {
                                    defaultSelect = defaultSelect.split(",");
                                }
                            }
                            let value = null;
                            let maxIndex = that.options.length - 1;
                            if (defaultSelect instanceof Array) {
                                value = [];
                                for (let i = 0; i < defaultSelect.length; i++) {
                                    let index = parseInt(defaultSelect[i]);
                                    if (maxIndex >= index) {
                                        value.push(that.prop.value(that.options[index]));
                                    }
                                }
                            } else {
                                let index = parseInt(defaultSelect);
                                if (maxIndex >= index) {
                                    value = that.prop.value(that.options[index]);
                                }
                            }

                            that.$emit("input", value, that);
                            that.$emit("value", value, that);
                            that.$emit("change", value, that);
                        }
                    }
                },
                getCache(key) {
                    if (!this.cache) {
                        return null;
                    }

                    this.deleteExpTimeCache();

                    let cacheElement = cache[key];
                    if (!cacheElement) {
                        return null;
                    }

                    let nowTime = new Date().getTime();
                    if (nowTime >= cacheElement["expTime"]) {
                        delete cache[key];
                        return null;
                    }
                    return cacheElement["data"];
                },
                setCache(key, value) {
                    if (!this.cache && value && value.isCache) {
                        return false;
                    }

                    this.deleteExpTimeCache();

                    let expTime = this.expTime;

                    cache[key] = {
                        isCache: true,
                        expTime: new Date().getTime() + expTime,
                        data: value
                    };
                },
                deleteExpTimeCache() {
                    for (let x in cache) {
                        if (cache.hasOwnProperty(x)) {
                            if (cache[x] && cache[x].expTime && new Date().getTime() >= cache[x].expTime) {
                                delete cache[x];
                            }
                        }
                    }
                },
                setSelect() {
                    this.$set(this, 'select', this.myGetSelect(this));
                },
                myEmit(val) {
                    let that = this;
                    that.queueVal.push(val);
                    that.tryEmit();
                },
                tryEmit() {
                    let that = this;
                    if (that.myLoading) {
                        setTimeout(function () {
                            // 回调
                            that.tryEmit();
                        }, 100)
                    } else {
                        that.doMyEmit()
                    }
                },
                doMyEmit() {
                    let that = this;
                    let queueVal = that.queueVal;
                    if (!queueVal || queueVal.length === 0) {
                        return;
                    }

                    let val = queueVal.pop();
                    that.queueVal = [];
                    let objArr = [];
                    if (that.multiple) {
                        val = that.select.join(',') || null;
                        that.options.forEach((item) => {
                            for (let i = 0; i < that.select.length; i++) {
                                if (that.prop.value(item) === that.select[i]) {
                                    objArr.push(item);
                                }
                            }
                        });
                    } else {
                        that.options.forEach((item) => {
                            if (that.prop.value(item) === val) {
                                objArr.push(item);
                            }
                        });
                    }

                    let selectdata = null;
                    let selectname = null;
                    if (objArr[0]) {
                        let nameLabel = [];
                        if (that.multiple) {
                            for (let i = 0; i < objArr.length; i++) {
                                let label = that.prop.label(objArr[i]);
                                nameLabel.push(label);
                            }
                            selectdata = objArr;
                        } else {
                            selectdata = objArr[0];
                            nameLabel.push(that.prop.label(objArr[0]))
                        }
                        selectname = nameLabel.toString();
                    }

                    that.$emit("selectdata", selectdata, that);
                    that.$emit("selectname", selectname, that);
                    that.$emit("input", val);
                }
            },
            created() {
                let that = this;
                that.init();
            }
        });

    })()
</script>



